package com.example.config;

import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.authz.Authorizer;
import org.apache.shiro.authz.ModularRealmAuthorizer;
import org.apache.shiro.mgt.SessionsSecurityManager;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Lazy;

import javax.servlet.Filter;
import java.util.*;

@Configuration
@Slf4j
@ConfigurationProperties(prefix = "api")
@Data
public class ShiroConfig {

    List<String> allowedPath;

    @Lazy
    @Bean
    public ShiroFilterFactoryBean shiroFilterFactoryBean(SessionsSecurityManager securityManager) {
        ShiroFilterFactoryBean factoryBean = new ShiroFilterFactoryBean();
        //配置自定义filter
        Map<String, Filter> filterMap = new HashMap<>();
        factoryBean.setFilters(filterMap);

        /*
         * filter配置规则参考官网
         * http://shiro.apache.org/web.html#urls-
         * 默认过滤器对照表
         * https://shiro.apache.org/web.html#default-filters
         */
        Map<String, String> filterRuleMap = new LinkedHashMap<>();
        allowedPath.forEach(path -> filterRuleMap.put(path, "anon"));
        //↑配置不参与验证的映射路径。


        // 关键：jwt验证过滤器。
        //↓ 此处采用shiro1.6新增的默认过滤器：authcBearer-BearerHttpAuthenticationFilter。
        filterRuleMap.put("/**", "authcBearer");
        //filterRuleMap.put("/**", "jwt");

        //↑ 注意：如果有其他过滤法则要配在/**上，则使用逗号间隔。

        factoryBean.setGlobalFilters(Collections.singletonList("noSessionCreation"));
        //↑ 这句非常关键：配置NoSessionCreationFilter，把整个项目变成无状态服务。
        //将corsFilter配置成全局，注意不能放在上面jwt的位置。只有放在这里才能不受"anon"等其他过滤器的影响，是真正的全局。

        factoryBean.setSecurityManager(securityManager);
        factoryBean.setFilterChainDefinitionMap(filterRuleMap);
        return factoryBean;
    }
    @Lazy
    @Bean
    protected Authorizer authorizer() {
        return new ModularRealmAuthorizer();
    }
}
